package com.kaguya.vams.controller;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kaguya.vams.common.constant.Constants;
import com.kaguya.vams.common.constant.HttpStatus;
import com.kaguya.vams.domain.Result;
import com.kaguya.vams.domain.dto.PassDto;
import com.kaguya.vams.domain.entity.SysRole;
import com.kaguya.vams.domain.entity.SysUser;
import com.kaguya.vams.domain.entity.SysUserRole;
import com.kaguya.vams.utils.MapUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author kaguya
 * @since 2021-07-28
 */
@Slf4j
@RestController
@RequestMapping("/sys/user")
public class SysUserController extends BaseController {

    /**
     * 返回当前用户信息
     *
     * @param principal
     * @return
     */
    @GetMapping("/getUserInfo")
    public Result getUserInfo(Principal principal) {
        String username = principal.getName();
        SysUser user = userService.getUserByUserName(username);
        return Result.ok(
                user
        );
    }


    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:user:list')")
    public Result list(String name) {

        //条件 如果userName存在则进行模糊查询
        QueryWrapper<SysUser> wr = new QueryWrapper<>();
        wr.like(StringUtils.isNotBlank(name), "username", name);

        //分页信息
        Page<SysUser> page = super.getPage();
        //数据库查询
        Page<SysUser> userPage = userService.page(page, wr);

        //设置角色信息
        userPage.getRecords().forEach(e -> {
            //根据userId查询所有与其关联的roles
            e.setRoles(this.getRoleListByUserId(e.getId()));
        });

        return Result.ok(userPage);
    }

    /**
     * 根据id查找单条信息 注意：返回角色的所有菜单权限id
     *
     * @return
     */
    @GetMapping("/info/{rowId}")
    @PreAuthorize("hasAnyAuthority('sys:user:update','sys:user:role')")
    public Result info(@PathVariable Long rowId) {
        //根据id查询
        SysUser user = userService.getById(rowId);

        //如果用户分配过角色，用户角色表有这个用户的id

        //根据userId查询所有与其关联的roles
        user.setRoles(this.getRoleListByUserId(user.getId()));

        return Result.ok(user);
    }

    public List<SysRole> getRoleListByUserId(Long userId) {
        //根据userId查询所有与其关联的roleId
        List<SysUserRole> list = userRoleService.list(
                new QueryWrapper<SysUserRole>()
                        .eq("user_id", userId));

        List<Long> roleIds = list.stream().map(e -> e.getRoleId()).collect(Collectors.toList());

        List<SysRole> sysRoles = null;
        if (roleIds.size() > 0) {
            //根据角色id获取所有与其相关的角色
            sysRoles = roleService.listByIds(roleIds);
        }
        //返回其角色id集合
        return sysRoles;
    }

    /**
     * 新增
     *
     * @return
     */
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:user:save')")
    public Result save(@Validated @RequestBody SysUser user) {
        //设置初始密码
        user.setPassword(encoder.encode(Constants.DEFAULT_PWD));

        if (StrUtil.isBlank(user.getPassword())) {
            return Result.msg(HttpStatus.FAIL.getCode(), "密码不能为空");
        }
        //调用方法，新增
        userService.save(user);
        return Result.ok();
    }

    /**
     * 分配角色
     *
     * @return
     */
    @Transactional
    @PutMapping("/setRole/{userId}")
    @PreAuthorize("hasAuthority('sys:user:role')")
    public Result setPerm(@PathVariable Long userId, @RequestBody Long[] roleIds) {

        //前台选中的新的角色id集合
        List<Long> RoleIds = Arrays.asList(roleIds);

        //转换成SysUserRole
        List<SysUserRole> urList = new ArrayList<>();
        RoleIds.stream().forEach(e -> {
            SysUserRole temp = new SysUserRole();
            temp.setUserId(userId);
            temp.setRoleId(e);

            urList.add(temp);
        });

        //清空该角色原有角色 - 根据id删除用户角色关系表
        userRoleService.remove(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        //重新添加分配该用户角色 - 根据传来的值批量新增用户角色关系表
        userRoleService.saveBatch(urList);

        //清空与该用户的权限缓存信息
        String userName = userService.getById(userId).getUsername();
        userService.clearUserAuthorityInfo(userName);

        return Result.ok();
    }

    /**
     * 修改
     *
     * @return
     */
    @PutMapping("/update")
    @PreAuthorize("hasAuthority('sys:user:update')")
    public Result update(@Validated @RequestBody SysUser user) {

        boolean update = userService.updateById(user);

        //修改后，清除该用户的权限缓存
        userService.clearUserAuthorityInfo(user.getUsername());

        log.info("修改" + (update == true ? "成功" : "失败"));

        return update == true ? Result.ok() : Result.fail();
    }

    /**
     * 重置密码
     */
    @PutMapping("/resetPwd")
    @PreAuthorize("hasAuthority('sys:user:repass')")
    public Result resetPwd(@RequestBody Long userId) {

        //根据id获取用户
        SysUser user = userService.getById(userId);
        //设置初始密码
        user.setPassword(encoder.encode(Constants.DEFAULT_PWD));
        //执行修改
        userService.updateById(user);

        return Result.ok();
    }

    /**
     * 修改密码
     */
    @PutMapping("/updatePass")
    public Result updatePass(@Validated @RequestBody PassDto passDto, Principal principal) {

        //获取当前用户
        SysUser sysUser = userService.getUserByUserName(principal.getName());
        //密码比对
        boolean matches = encoder.matches(passDto.getCurrentPass(), sysUser.getPassword());
        if (!matches) {
            return Result.msg(HttpStatus.FAIL.getCode(),"旧密码不正确！");
        }
        //设置新密码，执行修改
        sysUser.setPassword(encoder.encode(passDto.getPassword()));
        userService.updateById(sysUser);

        return Result.msg(HttpStatus.SUCCESS.getCode(),"修改成功！请重新登录！");
    }

    /**
     * 删除一条
     *
     * @return
     */
    @Transactional
    @DeleteMapping("/delete/{rowId}")
    @PreAuthorize("hasAuthority('sys:user:delete')")
    public Result delete(@PathVariable Long rowId) {

        //拿到用户以及用户名用于清除缓存
        SysUser user = userService.getById(rowId);
        //清空该用户缓存
        userService.clearUserAuthorityInfo(user.getUsername());

        //根据id删除
        userService.removeById(rowId);
        //删除用户角色关联表
        userRoleService.remove(new QueryWrapper<SysUserRole>().eq("user_id", rowId));

        return Result.ok();
    }

    /**
     * 批量删除
     *
     * @return
     */
    @Transactional
    @DeleteMapping("/batchRemove")
    @PreAuthorize("hasAuthority('sys:user:delete')")
    public Result batchRemove(@RequestBody Long[] idList) {

        List<Long> list = Arrays.asList(idList);

        //删除用户角色关联表
        userRoleService.remove(new QueryWrapper<SysUserRole>().in("user_id", list));
        //清空所有被删除用户的权限缓存
        list.forEach(id -> {
            SysUser user = userService.getById(id);
            userService.clearUserAuthorityInfo(user.getUsername());
        });

        //根据id删除
        userService.removeByIds(list);

        return Result.ok();
    }

}
